﻿<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>二叉树的非递归后序遍历算法实例详解</title>
  </head>
  <body>
    <script type="text/javascript">
    typedef struct{Node * p; int rvisited;}SNode //Node 是二叉树的结点结构，rvisited==1代表p所指向的结点的右结点已被访问过。

lastOrderTraverse(BiTree bt){
　　//首先，从根节点开始，往左下方走，一直走到头，将路径上的每一个结点入栈。
　　p = bt;
　　while(bt){
　　　　push(bt, 0); //push到栈中两个信息，一是结点指针，一是其右结点是否被访问过
　　　　bt = bt.lchild;
　　}

　　//然后进入循环体
　　while(!Stack.empty()){ //只要栈非空
　　　　sn = Stack.getTop(); // sn是栈顶结点

　　　　//注意，任意一个结点N，只要他有左孩子，则在N入栈之后，N的左孩子必然也跟着入栈了(这个体现在算法的后半部分)，所以当我们拿到栈顶元素的时候，可以确信这个元素要么没有左孩子，要么其左孩子已经被访问过，所以此时我们就不关心它的左孩子了，我们只关心其右孩子。

　　　　//若其右孩子已经被访问过，或是该元素没有右孩子，则由后序遍历的定义，此时可以visit这个结点了。
　　　　if(!sn.p.rchild || sn.rvisited){
　　　　　　p = pop();
　　　　　　visit(p);
　　　　}
　　　　else //若它的右孩子存在且rvisited为0，说明以前还没有动过它的右孩子，于是就去处理一下其右孩子。
　　　　{
　　　　　　//此时我们要从其右孩子结点开始一直往左下方走，直至走到尽头，将这条路径上的所有结点都入栈。

　　　　　　//当然，入栈之前要先将该结点的rvisited设成1，因为其右孩子的入栈意味着它的右孩子必将先于它被访问(这很好理解，因为我们总是从栈顶取出元素来进行visit)。由此可知，下一次该元素再处于栈顶时，其右孩子必然已被visit过了，所以此处可以将rvisited设置为1。
　　　　　　sn.rvisited = 1;

　　　　　　//往左下方走到尽头，将路径上所有元素入栈
　　　　　　p = sn.p.rchild;
　　　　　　while(p != 0){
　　　　　　　　push(p, 0);
　　　　　　　　p = p.lchild;
　　　　　　}
　　　　}//这一轮循环已结束，刚刚入栈的那些结点我们不必管它了，下一轮循环会将这些结点照顾的很好。
　　}
}
    </script>
  </body>
</html>